#include "Pawn.h"
#include "../Game/Engine.h"
#include "../Game/Player.h"
#include "../Game/Move.h"
#include "../Board/Square.h"

namespace Core
{

	Pawn::Pawn(Player * player, Square * square)
		:Piece(player, square)
	{
	}


	Pawn::~Pawn(void)
	{
	}

	std::string Pawn::name() const { return "Pawn"; }
	ChType Pawn::type() const { return ChType::ChPawn; }

	bool Pawn::isPromoted() const 
	{ 
		return _prom != NULL; 
	}

	void Pawn::promotedTo(Piece * val) 
	{
		//if(val->type() == ChKing || val->type() == ChPawn)
		//	throw "Invalid promotion";
		_prom = val; 
	}

	Piece * Pawn::promotedTo() const 
	{
		return _prom; 
	}


	bool Pawn::considerEatOrEnpassant(Move * mv) const
	{
		int d = this->color() == ChWhite ? +1 : -1;
		
		if(mv->to()->piece() != NULL)
		{
			// check eat
			if(mv->to()->piece()->color() != this->color() &&
				mv->to()->piece()->type() != ChKing)
			{
				mv->action(mv->action() | ChEat);
				mv->pieceEaten(mv->to()->piece());
				return true;
			}
		}
		else
		{
			// check if valid EN PASSANT
			const Move * last = Engine::instance()->lastMove();
			try
			{
				if(last != NULL &&
					last->piece()->type() == ChPawn &&
					last->piece()->color() != this->color() &&
					last->from() == Engine::instance()->chessboard()->at(mv->to()->row() + d, mv->to()->column()) &&
					last->to() == Engine::instance()->chessboard()->at(mv->to()->row() - d, mv->to()->column()))
				{
					mv->action(mv->action() | ChEnpassant);
					mv->pieceEaten(last->to()->piece());
					return true;
				}
			}
			catch(...) { }
		}
						
		return false;
	}

	void Pawn::considerPromotion(Move * mv) const
	{
		if((mv->to()->row() == 0 && this->color() == ChBlack) ||
			(mv->to()->row() == 7 && this->color() == ChWhite))
			mv->action(mv->action() | ChPromotion);
	}

	void Pawn::updateValidMoves()
	{
		Move * mv;
			
		int r = this->square()->row();
		int c = this->square()->column();
		int d = this->color() == ChWhite ? +1 : -1; // sarbaz sefid az payin be bala bayad beravad, siah barax
		const Chessboard * brd = Engine::instance()->chessboard();

		//**1**// barresie harekat 1 khane be jolo
		if(brd->checkBounds(r+d, c, 0, 0, false))
		{
			mv = new Move(this, brd->at(r+d, c));
			if(mv->to()->piece() == NULL)
			{
				considerPromotion(mv);
				_validMoves[mv->to()->key()] = mv;
			}
		}
			
		//**2**// barresie harekat 2 khane be jolo
		if(brd->checkBounds(r+2*d, c, 0, 0, false))
		{
			mv = new Move(this, brd->at(r+2*d, c));
			if(this->tracker()->moveCount() == 0 && brd->at(r+d, c)->piece() == NULL && mv->to()->piece() == NULL)
			{
				considerPromotion(mv);
				_validMoves[mv->to()->key()] = mv;
			}
		}

		//**3**// barresie harekat (Eat | EN PASSANT)
		if(brd->checkBounds(r+d, c+1, 0, 0, false))
		{
			mv = new Move(this,brd->at(r+d, c+1));
			if(considerEatOrEnpassant(mv))
			{
				considerPromotion(mv);
				_validMoves[mv->to()->key()] = mv;
			}
		}

		//**4**// barresie harekat (Eat | EN PASSANT)
		if(brd->checkBounds(r+d, c-1, 0, 0, false))
		{
			mv = new Move(this,brd->at(r+d, c-1));
			if(considerEatOrEnpassant(mv))
			{
				considerPromotion(mv);
				_validMoves[mv->to()->key()] = mv;
			}
		}
	}

}
